import java.io.ByteArrayInputStream;
import java.util.*;
import java.lang.reflect.*;



public class Biblio {
	
	public static Map<String,Integer> argFct = new HashMap<String,Integer>();
	
	public static Map<String,Method> methodFct = new HashMap<String,Method>();
	
	public Biblio() {
		argFct.put("somme", 2);
		argFct.put("produit", 2);
		argFct.put("division", 2);
		argFct.put("soustraction", 2);
		argFct.put("si", 2);
		argFct.put("sinon", 3);
		
		Class c = Biblio.class;
		Method[] tab = c.getMethods();
		
		Method  m;
		for (int i=0;i<tab.length;i++) {
			m = tab[i];
			if(m.getName().equals("somme"))
				methodFct.put("somme", m);
			
			if(m.getName().equals("produit"))
				methodFct.put("produit", m);
			
			if(m.getName().equals("division"))
				methodFct.put("division", m);
			
			if(m.getName().equals("soustraction"))
				methodFct.put("soustraction", m);
			
			if(m.getName().equals("si"))
				methodFct.put("si", m);
			
			if(m.getName().equals("sinon"))
				methodFct.put("sinon", m);
		}    
	};
	
	//marche pas avec double et int melangé
	public static Object somme(Vector<Object> v, HashMap<String, Object> penv)
	{	
		Object sum = new Boolean(false);
		boolean t1 = true, t2 = true ;
		int n = 0;
		
		while(t1 && n<v.size())
		{
			t1 = false;
			if (v.get(n) instanceof Integer || v.get(n) instanceof Double ) {
				t1 = true;
				if(v.get(n) instanceof Double)
					t2=false;
				}
		n++;	
		}			
		
		
		if(t1)
			if(t2) {
				sum=new Integer(0);
				for(int i=0; i<v.size(); i++)
					sum = (Integer)v.get(i) + (Integer)sum;
			}
			else {
				sum=new Double(0);
				for(int i=0; i<v.size(); i++)
					sum = (Double)v.get(i) + (Double)sum;
			}
		
		return sum;
	}
	
//	marche pas avec double et int melangé
	public static Object soustraction(Vector<Object> v,  HashMap<String, Object> penv){
		
		Object sous = new Boolean(false);
		
		
		if((v.get(0) instanceof Integer) || (v.get(0) instanceof Integer)) {
			sous = new Integer(0);
			sous = (Integer)v.get(0) - (Integer)v.get(1);
		}
		else		
			if((v.get(0) instanceof Integer) || (v.get(0) instanceof Double) &&
					(v.get(1) instanceof Integer) || (v.get(1) instanceof Double)){
				sous = new Double(0);
				sous = (Double)v.get(0) - (Double)v.get(1);
			
		}
			
		return sous;
	}
	
//	marche pas avec double et int melangé
	public static Object produit(Vector<Object> v,  HashMap<String, Object> penv)
	{	
		Object pro = new Boolean(false);
		boolean t1 = true, t2 = true ;
		int n = 0;
		
		while(t1 && n<v.size())
		{
			t1 = false;
			if (v.get(n) instanceof Integer || v.get(n) instanceof Double ) {
				t1 = true;
				if(v.get(n) instanceof Double)
					t2=false;
				}
		n++;	
		}			
		
		
		if(t1)
			if(t2) {
				pro=new Integer(1);
				for(int i=0; i<v.size(); i++)
					pro = (Integer)v.get(i) * (Integer)pro;
			}
			else {
				pro=new Double(1);
				for(int i=0; i<v.size(); i++)
					pro = (Double)v.get(i) * (Double)pro;
			}
		
		return pro;
	}
	
	//marche pas avec int
	public static Object division(Vector<Object> v,  HashMap<String, Object> penv){
		
		Object div = new Boolean(false);
		
		
		if((v.get(0) instanceof Integer) || (v.get(0) instanceof Double) &&
		   (v.get(1) instanceof Integer) || (v.get(1) instanceof Double) &&
		   (Double)v.get(1) != 0){
			div = new Double(1);
			div = (Double)v.get(0) / (Double)v.get(1);
			
		}
			
		return div;
	}

	//	marche pas avec int
	public static Object  egalite(Vector<Object> v,  HashMap<String, Object> penv){
		
		Object eq = new Boolean(false);
		
		
		if((v.get(0) instanceof Integer) || (v.get(0) instanceof Double) &&
		   (v.get(1) instanceof Integer) || (v.get(1) instanceof Double))
		{
			eq = v.get(0) == v.get(1);
		}
			
		return eq;
	}

	//	marche pas avec int
	public static Object  inegalite(Vector<Object> v,  HashMap<String, Object> penv){
		
		Object ineq = new Boolean(false);
		
		
		if((v.get(0) instanceof Integer) || (v.get(0) instanceof Double) &&
		   (v.get(1) instanceof Integer) || (v.get(1) instanceof Double)) 
		{
			ineq = v.get(0) != v.get(1);
		}
			
		return ineq;
	}

	//	marche pas avec int
	public static Object  pluspetit(Vector<Object> v,  HashMap<String, Object> penv){
		
		Object pp = new Boolean(false);
		
		
		if((v.get(0) instanceof Integer) || (v.get(0) instanceof Double) &&
		   (v.get(1) instanceof Integer) || (v.get(1) instanceof Double)) 
		{
			pp = (Double)v.get(0) < (Double)v.get(1);
		}
			
		return pp;
	}

	//	marche pas avec int
	public  static Object  plusgrand(Vector<Object> v,  HashMap<String, Object> penv){
		
		Object pg = new Boolean(false);
		
		
		if((v.get(0) instanceof Integer) || (v.get(0) instanceof Double) &&
		   (v.get(1) instanceof Integer) || (v.get(1) instanceof Double)) 
		{
			pg = (Double)v.get(0) > (Double)v.get(1);
		}
			
		return pg;
	}

	
	public static Object run(Vector<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
        
		HashMap<String, Object> env = new HashMap<String, Object>(penv);
		 
		String list = (String)v.get(0);
		list = (String)list.subSequence(1, list.length()-1);
		ByteArrayInputStream stream  = new ByteArrayInputStream(list.getBytes());
        Object i;

        System.out.print("stream : "+list+"\n");
        Logo parser = new Logo(stream);
        parser.initEnv(env);
        i = parser.run();
        
        return i;
	}
	
	
	public static Object si(Vector<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		Vector<Object> o = new Vector<Object>();

		
		if ((Boolean)v.get(0))
			return run(o,penv);
		
		return null;
	}
	
	
	public static Object sinon(Vector<Object> v,  HashMap<String, Object> penv) throws ParseException, Exception{
		Vector<Object> o = new Vector<Object>();
		
		if ((Boolean)v.get(0)) {
			o.add(v.get(1));
			return run(o,penv);
		}
		else {
			o.add(v.get(2));
			return run(o,penv);
		}
	}
	
}
